﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using System.Web.Security;
using AutoMapper;
using ClassLibrary;
using HinduShop.DbClassLib;
using HinduShop.Domain.Models.Account;
using HinduShop.UI.ViewModels;
using HinduShop.UI.ViewModels.Account;

namespace HinduShop.UI.Controllers
{
    public class AccountController : Controller
    {
        private readonly IAuthProvider authProvider;

        private readonly IUnitOfWorkFactory unitOfWorkFactory;

        private readonly IRepository<User> userRepository;

        public AccountController(
            IAuthProvider authProviderParam,
            IUnitOfWorkFactory unitOfWorkFactoryParam,
            IRepository<User> userRepositoryParam)
        {
            authProvider = authProviderParam;
            unitOfWorkFactory = unitOfWorkFactoryParam;
            userRepository = userRepositoryParam;
        }

        public ActionResult LogOn()
        {
            return View();
        }


        [HttpPost]
        public ActionResult LogOn(LogOnViewModel model, string returnUrl)
        {
            if (ModelState.IsValid)
            {
                using (IUnitOfWork uow = unitOfWorkFactory.Create())
                {
                    var user = userRepository.ReadByName("UserName", model.UserName);

                    uow.TransactionalFlush();

                    if (user == null)
                    {
                        ModelState.AddModelError("", "Такого юзера не существует");
                        return View(model);
                    }

                    /*if (Defender.VerifyPassword(user.PasswordHash, model.Password))
                    {
                        return Redirect(returnUrl ?? Url.Action("Index", "StoreManager"));
                    }*/
                    if (user.PasswordHash.Equals(model.Password))
                    {
                        FormsAuthentication.SetAuthCookie(model.UserName, false);
                        Session["roles"] = user.Roles;
                        return Redirect(returnUrl ?? Url.Action("Index", "StoreManager"));
                    }

                    // else
                    ModelState.AddModelError("", "Неверный пароль");
                    return View(model);
                }
            }
            else
            {
                return View();
            }
        }

        public ActionResult LogOff()
        {
            FormsAuthentication.SignOut();

            return RedirectToAction("Index", "StoreManager");
        }

        public ActionResult Register()
        {
            return View();
        }

        [HttpPost]
        public ActionResult Register(UserModel model)
        {
            if (ModelState.IsValid)
            {
                using (IUnitOfWork uow = unitOfWorkFactory.Create())
                {
                    IEnumerable<User> users = userRepository.ReadAll();

                    User user = users.FirstOrDefault(p => p.UserName == model.UserName);

                    if (user != null)
                    {
                        ModelState.AddModelError("", "Такой пользователь уже существует, измени Username");
                        return View(model);
                    }

                    /*const int saltSize = 5;
                    string salt = Defender.CreateSalt(saltSize);
                    string passwordHash = Defender.CreatePasswordHash(model.PasswordHash, salt);*/

                    Mapper.CreateMap<UserModel, User>();
                    User newUser = Mapper.Map<UserModel, User>(model);

                    Session["roles"] = newUser.Roles;
                    userRepository.SaveItem(newUser);
                    FormsAuthentication.SetAuthCookie(model.UserName, false);

                    uow.TransactionalFlush();

                    return RedirectToAction("SuccesfullRegister");
                }
            }

            // ModelState.IsValid == false
            return View(model);
        }

        public ActionResult DeleteUser(int id)
        {
            using (IUnitOfWork uow = unitOfWorkFactory.Create())
            {
                var user = userRepository.ReadById(id);
                if (user != null)
                {
                    userRepository.DeleteItem(user);
                    TempData["message"] = string.Format("{0} удален успешно", user.UserName);
                }
                else
                {
                    throw new Exception("Юзер с таким Id отсутствует в репозитории");
                }

                uow.TransactionalFlush();
            }

            return RedirectToAction("UserList");
        }

        [AuthorizeEnum(Roles=RolesEnum.Administrator)]
        public ActionResult AddUser()
        {
            return View(new UserModel());
        }

        [HttpPost]
        public ActionResult AddUser(UserModel model)
        {
            if (ModelState.IsValid == false)
            {
                return View(model);
            }

            using (IUnitOfWork uow = unitOfWorkFactory.Create())
            {

                Mapper.CreateMap<UserModel, User>();
                User newUser = Mapper.Map<UserModel, User>(model);

                userRepository.SaveItem(newUser);

                uow.TransactionalFlush();

                return RedirectToAction("UserList");
            }
        }

        public ActionResult UserList()
        {
            using (IUnitOfWork uow = unitOfWorkFactory.Create())
            {
                var users = userRepository.ReadAll();
                uow.TransactionalFlush();
                return View(new UserListViewModel(users));
            }
        }

        [Authorize]
        public ActionResult ChangePassword()
        {
            return View();
        }

        [Authorize]
        [HttpPost]
        public ActionResult ChangePassword(ChangePasswordModel model)
        {
            if (ModelState.IsValid)
            {
                // При некоторых сценариях сбоя операция смены пароля ChangePassword вызывает исключение,
                // а не возвращает значение false (ложь).
                bool changePasswordSucceeded;
                try
                {
                    MembershipUser currentUser = Membership.GetUser(User.Identity.Name, true /* userIsOnline */);
                    changePasswordSucceeded = currentUser.ChangePassword(model.OldPassword, model.NewPassword);
                }
                catch (Exception)
                {
                    changePasswordSucceeded = false;
                }

                if (changePasswordSucceeded)
                {
                    return RedirectToAction("ChangePasswordSuccess");
                }
                else
                {
                    ModelState.AddModelError("", "Неправильный текущий пароль или недопустимый новый пароль.");
                }
            }

            // Появление этого сообщения означает наличие ошибки; повторное отображение формы
            return View(model);
        }

        public ActionResult ChangePasswordSuccess()
        {
            return View();
        }

        #region Status Codes
        private static string ErrorCodeToString(MembershipCreateStatus createStatus)
        {
            // Полный список кодов состояния см. по адресу http://go.microsoft.com/fwlink/?LinkID=177550
            //.
            switch (createStatus)
            {
                case MembershipCreateStatus.DuplicateUserName:
                    return "Имя пользователя уже существует. Введите другое имя пользователя.";

                case MembershipCreateStatus.DuplicateEmail:
                    return "Имя пользователя для данного адреса электронной почты уже существует. Введите другой адрес электронной почты.";

                case MembershipCreateStatus.InvalidPassword:
                    return "Указан недопустимый пароль. Введите допустимое значение пароля.";

                case MembershipCreateStatus.InvalidEmail:
                    return "Указан недопустимый адрес электронной почты. Проверьте значение и повторите попытку.";

                case MembershipCreateStatus.InvalidAnswer:
                    return "Указан недопустимый ответ на вопрос для восстановления пароля. Проверьте значение и повторите попытку.";

                case MembershipCreateStatus.InvalidQuestion:
                    return "Указан недопустимый вопрос для восстановления пароля. Проверьте значение и повторите попытку.";

                case MembershipCreateStatus.InvalidUserName:
                    return "Указано недопустимое имя пользователя. Проверьте значение и повторите попытку.";

                case MembershipCreateStatus.ProviderError:
                    return "Поставщик проверки подлинности вернул ошибку. Проверьте введенное значение и повторите попытку. Если проблему устранить не удастся, обратитесь к системному администратору.";

                case MembershipCreateStatus.UserRejected:
                    return "Запрос создания пользователя был отменен. Проверьте введенное значение и повторите попытку. Если проблему устранить не удастся, обратитесь к системному администратору.";

                default:
                    return "Произошла неизвестная ошибка. Проверьте введенное значение и повторите попытку. Если проблему устранить не удастся, обратитесь к системному администратору.";
            }
        }
        #endregion

        public ActionResult SuccesfullRegister()
        {
            return View();
        }

        public ActionResult EditRoles(int userId)
        {
            using (IUnitOfWork uow = unitOfWorkFactory.Create())
            {
                var user = userRepository.ReadById(userId);



                uow.TransactionalFlush();

                return View(new EditRolesViewModel(user));
            }
        }

        [HttpPost]
        public ActionResult EditRoles(EditRolesViewModel model)
        {
            //EditRolesViewModel model1 = (EditRolesViewModel) Activator.CreateInstance(typeof(EditRolesViewModel));
            using (IUnitOfWork uow = unitOfWorkFactory.Create())
            {
                var user = userRepository.ReadById(model.UserId);

                if (model.AdminChecked == true)
                    user.AddRole(RolesEnum.Administrator);
                else
                    user.RemoveRole(RolesEnum.Administrator);
                if (model.UserChecked == true)
                    user.AddRole(RolesEnum.User);
                else
                    user.RemoveRole(RolesEnum.User);

                userRepository.SaveItem(user);
                uow.TransactionalFlush();

                return RedirectToAction("UserList");
            }
        }
    }
}
